home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Add-Ons / After Dark / Joe Judge / Fractal Popcorn ƒ / (Popcorn.c) next >
Encoding:
Text File  |  1989-08-28  |  5.8 KB  |  307 lines  |  [TEXT/MPS ]

  1. /*
  2.     Fractal Popcorn - by John Jeppson.
  3.     
  4.     This source code is in the public domain.
  5.     Written in MPW C.
  6.     
  7.     This program is an MPW Tool which implements Clifford A. Pickover's
  8.     "Fractal Popcorn" as described in "Computer Recreations" by
  9.     A.K.Dewdney in Scientific American, July 1989.  
  10.  
  11.     From the MPW Worksheet execute:
  12.     
  13.         Popcorn  top, left, edge
  14.     
  15.     where "top" and "left" are the corner of the target square and "edge"
  16.     is its side.
  17.     
  18.     After the display is drawn you will hear a SysBeep.  You
  19.     may interrupt a partially completed display by clicking the
  20.     mouse or pressing any key. You may not see any immediate
  21.     effect, but the drawing will soon terminate with a double
  22.     SysBeep at the end of the current inner loop.
  23.  
  24.     You may print the completed display by pressing "p".
  25.  
  26.     Return to the shell with the close box.
  27.     
  28.     
  29.     Popcorn -6, -6, 12        - an overall view of the 12 unit square about
  30.                               the origin.
  31.                             
  32.     Popcorn -3, -3, 6         - the central portion of the above. This is about
  33.                               the level of magnification of the illustration
  34.                               in Scientific American.
  35.  
  36.     Popcorn -2.5, -2.5, 2   - enlargements of a single "kernel".
  37.     Popcorn -2,   -2,   1
  38.  
  39. */
  40.  
  41. #include <Types.h>
  42. #include <Windows.h>
  43. #include <Memory.h>
  44. #include <Printing.h>
  45. #include <Fonts.h>
  46. #include <Resources.h>
  47. #include <OSUtils.h>
  48. #include <Math.h>
  49. #include <StdLib.h>
  50.  
  51. #define h                0.05
  52.  
  53. #define windowTop        40
  54. #define windowLeft        4
  55. #define windowEdge        200
  56. #define windowTitle        "\pPopcorn"
  57.  
  58. #define nil                0L
  59.  
  60.  
  61.  
  62. /**** globals ****/
  63.  
  64.     WindowPtr    display;
  65.     Boolean        alreadyDrawn;
  66.     BitMap        offScreen;
  67.  
  68.     extended    top, left, edge;
  69.     extended    x0, y0;
  70.     extended    increment, scale;
  71.  
  72.  
  73. void plot (extended x, extended y)
  74. {
  75.     short xi, yi;
  76.     
  77.     xi = rint(x);
  78.     yi = rint(y);
  79.     
  80.     MoveTo (xi, yi);
  81.     Line (0,0);
  82. }
  83.  
  84.  
  85. void drawContents(WindowPtr w)
  86. {
  87.     short        j, k, n;
  88.     extended    x, y, xx, yy;
  89.     EventRecord    evt;
  90.     
  91.  
  92.     EraseRect(&(w->portRect));
  93.  
  94.     if ( alreadyDrawn )
  95.         CopyBits (&offScreen, &(display->portBits),
  96.                     &(offScreen.bounds), &(offScreen.bounds),
  97.                         srcCopy, nil);
  98.  
  99.     else
  100.     {
  101.         while ( GetNextEvent(mDownMask + keyDownMask, &evt) )
  102.             {};  /* dump event queue */
  103.             
  104.         PenNormal();
  105.         for ( j = 1; j <= 50; ++j )
  106.         {
  107.             if ( EventAvail(mDownMask + keyDownMask, &evt) )
  108.                 break;
  109.             for ( k = 1; k <= 50; ++k )
  110.             {
  111.                 x = left + (increment * j);
  112.                 y = top  + (increment * k);
  113.                 
  114.                 for ( n = 1; n <= 50; ++n )
  115.                 {
  116.                     xx = x - h * sin(y + tan(3 * y));
  117.                     yy = y - h * sin(x + tan(3 * x));
  118.                     x = xx;
  119.                     y = yy;
  120.  
  121.                     plot (scale * x + x0, scale * y + y0);
  122.                 }
  123.             }
  124.         }
  125.         alreadyDrawn = true;
  126.         CopyBits (&(display->portBits), &offScreen,
  127.                     &(offScreen.bounds), &(offScreen.bounds),
  128.                         srcCopy, nil);
  129.         SysBeep(1);
  130.     }
  131. }
  132.  
  133.  
  134. /**** generic tool stuff ****/
  135.  
  136.  
  137. void doUpdate(WindowPtr w)
  138. {
  139.     GrafPtr    savePort;
  140.     
  141.     GetPort(&savePort);
  142.     SetPort(w);
  143.     ClipRect(&(w->portRect));
  144.     BeginUpdate(w);
  145.         drawContents(w);
  146.     EndUpdate(w);
  147.     SetPort(savePort);
  148. }
  149.  
  150.  
  151. void makeOffScreen()   /* set up offscreen bitmap to store image */
  152. {
  153.     Size        sizeOfOff;
  154.     short        offRowBytes;
  155.  
  156.     offRowBytes = (((windowEdge - 1) / 16) + 1) * 2;
  157.     sizeOfOff = windowEdge * offRowBytes;
  158.     
  159.     offScreen.baseAddr = (QDPtr) NewPtr(sizeOfOff);
  160.     offScreen.rowBytes = offRowBytes;
  161.     SetRect(&(offScreen.bounds), 0, 0, windowEdge, windowEdge);
  162. }
  163.  
  164.  
  165. void makeWindow()
  166. {
  167.     Rect    bounds;
  168.  
  169.     SetRect(&bounds, windowLeft, windowTop, windowLeft + windowEdge, windowTop + windowEdge);
  170.     display = NewWindow(nil, &bounds, windowTitle, true, noGrowDocProc, (WindowPtr) -1, true, 0L);
  171. }
  172.  
  173.  
  174. void printWindow()
  175. {
  176.     TPPrPort    pport;
  177.     THPrint        hPrint;
  178.     TPrStatus    PrStatus;
  179.     GrafPtr        oldPort;  
  180.     Boolean     notCancelled = true;
  181.     Boolean        drop;
  182.  
  183.     GetPort (&oldPort);
  184.     PrOpen();
  185.  
  186.     SetFractEnable(true);
  187.     SetFScaleDisable(true);
  188.  
  189.     hPrint = (THPrint) NewHandle(sizeof(TPrint));
  190.     if (ResError())
  191.     {
  192.         printf ("Printing Error %d\n", ResError());
  193.         SysBeep(1);
  194.         PrClose();
  195.         return;
  196.     }
  197.     
  198.     drop = PrValidate(hPrint);
  199.     notCancelled = PrJobDialog (hPrint);
  200.         
  201.     if (notCancelled)
  202.     {
  203.         pport = PrOpenDoc(hPrint, nil, nil);
  204.         if ( PrError() == noErr )
  205.         {
  206.             PrOpenPage(pport, nil);
  207.             if (PrError()==noErr)
  208.                 CopyBits (&offScreen, &(pport->gPort.portBits),
  209.                     &(offScreen.bounds), &(offScreen.bounds),
  210.                         srcCopy, nil);
  211.             PrClosePage(pport);
  212.         }
  213.         PrCloseDoc(pport);
  214.     }
  215.     if ( ((**hPrint).prJob.bJDocLoop == bSpoolLoop)
  216.              && (PrError() == noErr) )
  217.         PrPicFile (hPrint, nil, nil, nil, &PrStatus);
  218.         
  219.     SetFractEnable(false);
  220.     SetFScaleDisable(false);
  221.  
  222.     PrClose();
  223.  
  224.     SetPort (oldPort);
  225. }
  226.  
  227.  
  228. void mainLoop()
  229. {
  230.     Boolean            done = false;
  231.     EventRecord        theEvent;
  232.     WindowPtr        whichWindow;
  233.     short            part;
  234.     
  235.     while ( !done )
  236.     {
  237.         if ( GetNextEvent(everyEvent, &theEvent) )
  238.         {
  239.             switch ( theEvent.what )
  240.             {
  241.                 case updateEvt:
  242.                     doUpdate(display);
  243.                     break;
  244.  
  245.                 case mouseDown:
  246.                     part = FindWindow(theEvent.where, &whichWindow);
  247.                     if ( (whichWindow == display) && (part == inGoAway) )
  248.                         done = true;
  249.                     else
  250.                         SysBeep(1);
  251.                     break;
  252.  
  253.                 case keyDown:
  254.                     if ( 'p' == (theEvent.message & charCodeMask) )
  255.                         printWindow();
  256.                     else
  257.                         SysBeep(1);
  258.                     break;
  259.             }
  260.         }
  261.     }
  262. }
  263.  
  264.  
  265. void cleanUp()
  266. {
  267.     DisposeWindow(display);
  268.     DisposPtr((Ptr) offScreen.baseAddr);
  269. }
  270.  
  271.  
  272. int main (
  273.     int  argc,            /* number of arguments */
  274.     char *argv[],        /* pointer to array of argument strings */
  275.     char *envp[])        /* pointer to array of variable definitions */
  276. {
  277.     #pragma unused (envp)
  278.  
  279.     InitGraf((Ptr) &qd.thePort);
  280.     SetFScaleDisable(true);
  281.     InitCursor();
  282.     
  283.     if ( argc != 4 )
  284.     {
  285.         printf ("### Wrong Number of Parameters ###\n");
  286.         return 2;
  287.     }
  288.     
  289.     top            = atof(argv[1]);
  290.     left        = atof(argv[2]);
  291.     edge        = atof(argv[3]);
  292.  
  293.     increment    = edge / 50;
  294.     scale         = windowEdge / edge;
  295.     x0            = (windowEdge / 2) - ((left + (edge / 2)) * scale);
  296.     y0            = (windowEdge / 2) - ((top  + (edge / 2)) * scale);
  297.  
  298.     alreadyDrawn = false;
  299.     
  300.     makeOffScreen();
  301.     makeWindow();
  302.     mainLoop();
  303.     cleanUp();
  304.  
  305.     return 0;
  306. }
  307.